﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using JAAF.Builders;
using JAAF.Collections;
using System.Windows.Media;
using System.Windows.Media.Effects;

namespace JAAF.UI.WPF
{
    /// <summary>
    /// An adapter class that provides <see cref="IViewspace"> functionality to a 
    /// <see cref="ContentControl"/> WPF control.</see>
    /// </summary>
    public class ContentControlViewspaceAdapter : ContentControl, IViewspace
    {
        #region Instance Data


        //ContentControl m_oPanel;

        private ViewDictionary m_lstViews;

        private IView m_oActiveView;

        private ReadOnlyKeyedCollection<string, IView> m_colViewsRO;

        private Grid m_oContainer;

        private TextBlock m_txtTitle;

        #endregion


        #region Initialization

        public ContentControlViewspaceAdapter()
        {
            this._Initialize();
        }

        /// <summary>
        /// Creates a new instance of the ContentControlViewspaceAdapter
        /// with a reference to the control that is about to be adapted.
        /// </summary>
        /// <param name="_oAdaptedControl">The control to be adapted.</param>
        public ContentControlViewspaceAdapter(ContentControl _oAdaptedControl)
        {
            this._Initialize();
        }

        private void _Initialize()
        {
            m_lstViews = new ViewDictionary();
            m_colViewsRO = m_lstViews.AsReadOnly();

            m_oContainer = new Grid();
            m_oContainer.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(0, GridUnitType.Auto) });
            m_oContainer.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(100, GridUnitType.Star) });

            m_txtTitle = new TextBlock()
                             {
                                 FontSize = 18,
                                 FontWeight = FontWeights.Bold,
                                 Foreground = new SolidColorBrush(Colors.White),
                                 Margin = new Thickness(0, 0, 0, 10),
                             };

            DropShadowEffect oFX = new DropShadowEffect()
                                   {
                                       Opacity = 0.7,
                                       BlurRadius = 5,
                                       Direction = 320,
                                       ShadowDepth = 2,
                                       RenderingBias = RenderingBias.Performance
                                   };

            m_txtTitle.Effect = oFX;

            m_txtTitle.SetValue(Grid.RowProperty, 0);
            m_oContainer.Children.Add(m_txtTitle);

            this.Content = m_oContainer;
        }


        #endregion

        public event EventHandler<ViewspaceCancelEventArgs> ViewClosing;

        public event EventHandler<ViewspaceEventArgs> ViewActivated;

        public ReadOnlyKeyedCollection<string, IView> Views
        {
            get
            {
                return m_colViewsRO;
            }
        }

        public object ActiveView
        {
            get
            {
                return m_oActiveView;
            }
        }


        public void ShowView(IView a_oView)
        {
            if (a_oView == m_oActiveView)
            {
                return;
            }

            lock (m_lstViews)
            {
                if (m_lstViews.Contains(a_oView))
                {
                    m_lstViews.Remove(a_oView);
                }

                m_lstViews.Add(a_oView);
                this._RegisterViewEvents(a_oView);

                this._ShowViewInternal(a_oView);
            }

        }

        private FrameworkElement _CastView(IView _aoView)
        {
            return (FrameworkElement)_aoView;
        }

        private void _ShowViewInternal(IView a_oView)
        {
            UIElement oNewView = a_oView as UIElement;
            if (oNewView == null)
                throw new ArgumentException("The view provided cannot be displayed because it does not Derive from System.Windows.FrameworkElement"); //RESOURCE

            m_txtTitle.Text = null;

            if (m_oActiveView != null)
            {
                m_oContainer.Children.Remove((UIElement)m_oActiveView);
            }

            oNewView.SetValue(Grid.RowProperty, 1);
            m_oContainer.Children.Add(oNewView);

            this._SetTitle(a_oView.Title);

            m_oActiveView = a_oView;
            oNewView.Focus();
        }

        private void _CloseViewInternal(IView _oView)
        {
            m_txtTitle.Text = null;
            m_oContainer.Children.Remove((UIElement)_oView);
            m_oActiveView = null;
        }

        public void CloseView(IView _oView)
        {
            lock (m_lstViews)
            {
                int ixView = m_lstViews.IndexOf(_oView);
                int ixNextView = -1;

                if (ixView == -1)
                    return;

                m_lstViews.RemoveAt(ixView);
                this._UnregisterViewEvents(_oView);

                if (_oView == m_oActiveView)
                {
                    this._CloseViewInternal(_oView);

                    ixNextView = ixView - 1;
                    if (ixNextView == -1)
                        ixNextView = 0;

                    if (ixNextView < m_lstViews.Count)
                    {
                        this._ShowViewInternal(m_lstViews[ixNextView]);
                    }
                }
            }
        }

        public void ActivateView(IView _oView)
        {
            FrameworkElement oView = this._CastView(_oView);

            if (!oView.IsEnabled)
                oView.IsEnabled = true;

            oView.Focus();
        }

        public void HideView(IView _oView)
        {
            if (!m_lstViews.Contains(_oView))
                return;

            this._CastView(_oView).Visibility = System.Windows.Visibility.Collapsed;
        }

        public void EnableView(IView _oView)
        {
            if (!m_lstViews.Contains(_oView))
                return;

            this._CastView(_oView).IsEnabled = true;
        }

        public void DisableView(IView _oView)
        {
            if (!m_lstViews.Contains(_oView))
                return;

            this._CastView(_oView).IsEnabled = false;
        }

        private void _UnregisterViewEvents(IView _oView)
        {
            _oView.ViewClosed -= this._OnViewClosed;
        }

        private void _RegisterViewEvents(IView _oView)
        {
            _oView.ViewClosed += this._OnViewClosed;
        }

        private void _OnViewClosed(object _oSender, EventArgs _oArgs)
        {
            ((IViewspace)this).CloseView((IView)_oSender);
        }

        private void _SetTitle(string _sTitle)
        {
            m_txtTitle.Text = _sTitle;

            if (string.IsNullOrWhiteSpace(_sTitle))
                m_txtTitle.Visibility = Visibility.Collapsed;
            else
                m_txtTitle.Visibility = Visibility.Visible;

        }
    }
}
